#include <iostream>
#include <vector>
using namespace std;

// https://leetcode.cn/problems/permutations/
// 46. 全排列
// 给定一个不含重复数字的数组 nums ，返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
void printVec(const vector<int>& vec){
    for(int e: vec)
        cout << e << " ";
    cout << endl;
}
// 回溯法-不带debug信息
class Solution {
private:
    vector<vector<int>> res;
    vector<bool> used;  // 使用used[i]判断nums[i]是否被使用过了
    // p中保存了一个有 index 个元素的排列。
    // 向这个排列的末尾添加第 index + 1 个元素，获得一个有 index+1 个元素的排列
    // nums数组的元素组成所有排列，index表示现在正在处理第几个元素，p是在递归过程中找到的一个排列
    void generatePermutation(const vector<int>& nums, int index, vector<int>& p) {
        if(index == nums.size()) {
            // p中已经包含了一个排列，此排列了所有元素。此时将结果保存起来
            res.push_back(p);
            return;
        }
        for(int i = 0; i < nums.size(); i++) {
            // 对于已经存在index个元素，不能再使用了
            if(!used[i]) {
                // 将 nums[i]添加在p中
                p.push_back(nums[i]);
                used[i] = true;
                generatePermutation(nums, index+1, p);
                // 当前的元素使用完后，尝试nums中的其他的元素。
                // 递归函数自动会回去，但是设置的其他变量如果有必要的话，也必须要回归原位
                // 让p和used恢复原状，再进行下一轮的循环
                p.pop_back();
                used[i] = false;
            }
        }

    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        res.clear();
        if(nums.size() == 0)
            return res;

        used = vector<bool>(nums.size(), false);    // 一定不要忘记初始化used
        vector<int> p;
        generatePermutation(nums, 0, p);

        return res;
    }
};


int main() {
    int nums[] = {1, 2, 3};
    vector<int> vec(nums, nums + sizeof(nums)/sizeof(int) );

    vector<vector<int>> res = Solution().permute(vec);
    cout<<"print permutation:"<<endl;
    for(int i = 0 ; i < res.size() ; i ++)
        printVec(res[i]);
    return 0;
}
